import { Application, TreeNode, GameEntity, Color, Rectangle, EngineUtil, SystemManager } from '@egret/engine';
import { Matcher, component, Component, system } from '@egret/ecs';
import { DrawCallCollector } from '@egret/render';
import { EditorWindowUtil, EditorUtil, EntitySelector, Selected, EditorWindow, LastSelected, Tools, BaseEditorSystem } from '@egret/editor';
import { Reflect as Reflect$1 } from '@egret/basis';
import { getHideFlags, AssetEntity, hideFlag } from '@egret/core';

/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0

THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.

See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */

var extendStatics = function (d, b) {
    extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return extendStatics(d, b);
};

function __extends(d, b) {
    extendStatics(d, b);
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}

function __decorate(decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
}

function __awaiter(thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

function __generator(thisArg, body) {
    var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
}

//
var _array2 = [0.0, 0.0];
var _array3 = [0.0, 0.0, 0.0];
var _array4 = [0.0, 0.0, 0.0, 0.0];
/**
 *
 */
var InspectorWindow = /** @class */ (function (_super) {
    __extends(InspectorWindow, _super);
    function InspectorWindow() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        /** */
        _this._imguiCount = 0;
        _this._helpStringBuffer = new ImGui.ImStringBuffer(2048, "");
        _this._entitySelecteor = Application.instance.globalEntity.getComponent(EntitySelector);
        _this._groups = [];
        return _this;
    }
    /** TODO remove */
    InspectorWindow.prototype._propertyHasGetterSetter = function (target, propName) {
        var prototype = Object.getPrototypeOf(target);
        while (prototype) {
            var descriptror = Object.getOwnPropertyDescriptor(prototype, propName);
            if (descriptror && descriptror.get && descriptror.set) {
                return true;
            }
            prototype = Object.getPrototypeOf(prototype);
        }
        return false;
    };
    /** */
    InspectorWindow.prototype._imProprety = function (instance, propertyInfo) {
        if (propertyInfo.isArray) {
            return; // TODO
        }
        var name = propertyInfo.name, option = propertyInfo.option;
        var get = option && option.get ? option.get : null;
        var set = option && option.set ? option.set : null;
        var labelName = name + "###" + this._imguiCount++; // TODO
        var changed = false;
        // ImGui.Indent(8);
        switch (propertyInfo.editType) {
            case "boolean" /* Boolean */: {
                var value_1 = (get !== null ? get() : instance[name]);
                changed = ImGui.Checkbox(labelName, function (v) {
                    if (v === void 0) { v = value_1; }
                    return value_1 = v;
                });
                if (changed) {
                    if (set !== null) {
                        set(value_1);
                    }
                    else {
                        instance[name] = value_1;
                    }
                }
                break;
            }
            case "uint" /* Uint */: {
                var value_2 = (get !== null ? get() : instance[name]);
                if (option && option.minimum !== undefined && option.maximum !== undefined) {
                    changed = ImGui.SliderInt(labelName, function (v) {
                        if (v === void 0) { v = value_2; }
                        return value_2 = v;
                    }, Math.max(option.minimum, 0), option.maximum);
                }
                else {
                    changed = ImGui.DragInt(labelName, function (v) {
                        if (v === void 0) { v = value_2; }
                        return value_2 = v;
                    }, 1, // TODO step
                        Math.max((option && option.minimum !== undefined) ? option.minimum : 0, 0), (option && option.maximum !== undefined) ? option.maximum : 2147483647);
                }
                if (changed) {
                    if (set !== null) {
                        set(value_2);
                    }
                    else {
                        instance[name] = value_2;
                    }
                }
                break;
            }
            case "int" /* Int */: {
                var value_3 = (get !== null ? get() : instance[name]);
                if (option && option.minimum !== undefined && option.maximum !== undefined) {
                    changed = ImGui.SliderInt(labelName, function (v) {
                        if (v === void 0) { v = value_3; }
                        return value_3 = v;
                    }, option.minimum, option.maximum);
                }
                else {
                    changed = ImGui.DragInt(labelName, function (v) {
                        if (v === void 0) { v = value_3; }
                        return value_3 = v;
                    }, 1, // TODO step
                        (option && option.minimum !== undefined) ? option.minimum : -2147483647, (option && option.maximum !== undefined) ? option.maximum : 2147483647);
                }
                if (changed) {
                    if (set !== null) {
                        set(value_3);
                    }
                    else {
                        instance[name] = value_3;
                    }
                }
                break;
            }
            case "float" /* Float */: {
                var value_4 = (get !== null ? get() : instance[name]);
                if (option && option.minimum !== undefined && option.maximum !== undefined) {
                    changed = ImGui.SliderFloat(labelName, function (v) {
                        if (v === void 0) { v = value_4; }
                        return value_4 = v;
                    }, option.minimum, option.maximum);
                }
                else {
                    changed = ImGui.DragFloat(labelName, function (v) {
                        if (v === void 0) { v = value_4; }
                        return value_4 = v;
                    }, 1.0, // TODO step
                        (option && option.minimum !== undefined) ? option.minimum : -3.4E38, (option && option.maximum !== undefined) ? option.maximum : 3.4E38);
                }
                if (changed) {
                    if (set !== null) {
                        set(value_4);
                    }
                    else {
                        instance[name] = value_4;
                    }
                }
                break;
            }
            case "string" /* String */: {
                var value = (get !== null ? get() : instance[name]);
                this._helpStringBuffer.buffer = value;
                changed = ImGui.InputText(labelName, this._helpStringBuffer, ImGui.IM_ARRAYSIZE(this._helpStringBuffer));
                if (changed) {
                    if (set !== null) {
                        set(this._helpStringBuffer.buffer);
                    }
                    else {
                        instance[name] = this._helpStringBuffer.buffer;
                    }
                }
                break;
            }
            case "vector2" /* Vector2 */: {
                var value = (get !== null ? get() : instance[name]);
                _array2[0] = value.x;
                _array2[1] = value.y;
                changed = ImGui.DragFloat2(labelName, _array2);
                if (changed) {
                    if (set !== null) {
                        set(value);
                    }
                    else {
                        value.x = _array2[0];
                        value.y = _array2[1];
                        if (this._propertyHasGetterSetter(instance, name)) {
                            instance[name] = value;
                        }
                    }
                }
                break;
            }
            case "vector3" /* Vector3 */: {
                var value = (get !== null ? get() : instance[name]);
                _array3[0] = value.x;
                _array3[1] = value.y;
                _array3[2] = value.z;
                changed = ImGui.DragFloat3(labelName, _array3);
                if (changed) {
                    if (set !== null) {
                        set(value);
                    }
                    else {
                        value.x = _array3[0];
                        value.y = _array3[1];
                        value.z = _array3[2];
                        if (this._propertyHasGetterSetter(instance, name)) {
                            instance[name] = value;
                        }
                    }
                }
                break;
            }
            case "vector4" /* Vector4 */: {
                var value = (get !== null ? get() : instance[name]);
                _array4[0] = value.x;
                _array4[1] = value.y;
                _array4[2] = value.z;
                _array4[3] = value.w;
                changed = ImGui.DragFloat3(labelName, _array4);
                if (changed) {
                    if (set !== null) {
                        set(value);
                    }
                    else {
                        value.x = _array4[0];
                        value.y = _array4[1];
                        value.z = _array4[2];
                        value.w = _array4[3];
                        if (this._propertyHasGetterSetter(instance, name)) {
                            instance[name] = value;
                        }
                    }
                }
                break;
            }
            case "quaternion" /* Quaternion */: {
                var value = (get !== null ? get() : instance[name]);
                _array4[0] = value.rawData[0];
                _array4[1] = value.rawData[1];
                _array4[2] = value.rawData[2];
                _array4[3] = value.rawData[3];
                changed = ImGui.DragFloat4(labelName, _array4);
                if (changed) {
                    if (set !== null) {
                        set(value);
                    }
                    else {
                        value.rawData[0] = _array4[0];
                        value.rawData[1] = _array4[1];
                        value.rawData[2] = _array4[2];
                        value.rawData[3] = _array4[3];
                        if (this._propertyHasGetterSetter(instance, name)) {
                            instance[name] = value;
                        }
                    }
                }
                break;
            }
            case "size" /* Size */: {
                var value = (get !== null ? get() : instance[name]);
                _array2[0] = value.w;
                _array2[1] = value.h;
                changed = ImGui.DragFloat2(labelName, _array2);
                if (changed) {
                    if (set !== null) {
                        set(value);
                    }
                    else {
                        value.w = _array2[0];
                        value.h = _array2[1];
                        if (this._propertyHasGetterSetter(instance, name)) {
                            instance[name] = value;
                        }
                    }
                }
                break;
            }
            case "color" /* Color */: {
                // const misc_flags = (hdr.value ? ImGuiColorEditFlags.HDR : 0) | (drag_and_drop.value ? 0 : ImGuiColorEditFlags.NoDragDrop) | (alpha_half_preview.value ? ImGuiColorEditFlags.AlphaPreviewHalf : (alpha_preview.value ? ImGuiColorEditFlags.AlphaPreview : 0)) | (options_menu.value ? 0 : ImGuiColorEditFlags.NoOptions); // TODO
                var value = (get !== null ? get() : instance[name]);
                var imValue = EditorWindowUtil.vector4ToImVec4(value.r, value.g, value.b, value.a);
                changed = ImGui.ColorEdit4(labelName, imValue, ImGui.ImGuiColorEditFlags.Float);
                if (changed) {
                    value.r = imValue.x;
                    value.g = imValue.y;
                    value.b = imValue.z;
                    value.a = imValue.w;
                    if (this._propertyHasGetterSetter(instance, name)) {
                        instance[name] = value;
                    }
                }
                break;
            }
            case "rectangle" /* Rectangle */: {
                var value = (get !== null ? get() : instance[name]);
                _array4[0] = value.x;
                _array4[1] = value.y;
                _array4[2] = value.w;
                _array4[3] = value.h;
                changed = ImGui.DragFloat4(labelName, _array4);
                if (changed) {
                    if (set !== null) {
                        set(value);
                    }
                    else {
                        value.x = _array4[0];
                        value.y = _array4[1];
                        value.w = _array4[2];
                        value.h = _array4[3];
                        if (this._propertyHasGetterSetter(instance, name)) {
                            instance[name] = value;
                        }
                    }
                }
                break;
            }
            case "enum" /* Enum */: {
                if (option && option.listItems) {
                    if (Array.isArray(option.listItems)) {
                        var items = option.listItems.map(function (item) { return item.label; });
                        var values = option.listItems.map(function (item) { return item.value; });
                        var value_5 = values.indexOf(get !== null ? get() : (instance[name]));
                        changed = ImGui.Combo(labelName, function (v) {
                            if (v === void 0) { v = value_5; }
                            return value_5 = v;
                        }, items, ImGui.IM_ARRAYSIZE(items));
                        if (changed) {
                            if (set !== null) {
                                set(value_5);
                            }
                            else {
                                instance[name] = values[value_5];
                            }
                        }
                    }
                }
                break;
            }
            case "entity" /* Entity */: { // TODO
                break;
            }
            case "component" /* Component */: { // TODO
                break;
            }
            case "asset" /* Asset */: { // TODO
                break;
            }
            case "button" /* Button */: { // TODO
                break;
            }
            case "nested" /* Nested */: {
                var value = instance[name];
                var opened = ImGui.TreeNode(labelName); // TODO path
                if (ImGui.IsItemClicked());
                if (opened) {
                    for (var _i = 0, _a = EditorUtil.getEditableProperties(value); _i < _a.length; _i++) {
                        var info = _a[_i];
                        this._imProprety(value, info);
                    }
                    ImGui.TreePop();
                }
                break;
            }
        }
        // ImGui.Unindent();
    };
    /** */
    InspectorWindow.prototype._imEntity = function (entity) {
        for (var _i = 0, _a = EditorUtil.getEditableProperties(entity); _i < _a.length; _i++) {
            var propertyInfo = _a[_i];
            this._imProprety(entity, propertyInfo);
        }
        ImGui.Separator();
        ImGui.PushItemWidth(-110.0);
        for (var _b = 0, _c = entity.components; _b < _c.length; _b++) {
            var component_1 = _c[_b];
            var hideFlag = getHideFlags(component_1);
            if (hideFlag !== null && hideFlag.hide) {
                continue;
            }
            this._imComponent(component_1);
        }
        ImGui.PopItemWidth();
    };
    /** */
    InspectorWindow.prototype._imComponent = function (component) {
        var menu = component.constructor.componentMenu;
        var componentName = (menu !== "" ? menu + "/" : "") + Reflect$1.getQualifiedClassName(component);
        var nodeFlags = ImGui.ImGuiTreeNodeFlags.None;
        if (this._entitySelecteor.isComponentSelected(component)) {
            nodeFlags |= ImGui.ImGuiTreeNodeFlags.Selected | ImGui.ImGuiTreeNodeFlags.DefaultOpen;
        }
        var opened = ImGui.CollapsingHeader(componentName + "###" + component.uuid, nodeFlags);
        if (opened) {
            for (var _i = 0, _a = EditorUtil.getEditableProperties(component); _i < _a.length; _i++) {
                var propertyInfo = _a[_i];
                this._imProprety(component, propertyInfo);
            }
        }
    };
    /**
     * @_inheritDoc
     * @override
     */
    InspectorWindow.prototype.initialize = function (defaultEnabled, entity, config) {
        var _this = this;
        if (config === void 0) { config = null; }
        _super.prototype.initialize.call(this, defaultEnabled, entity, config); // TODO
        var application = Application.instance;
        this._entitySelecteor = application.globalEntity.getComponent(EntitySelector);
        application.contexts.map(function (context) {
            _this._groups.push(context.getGroup(Matcher.create(context.entityClass, false, Selected)));
        });
    };
    /**
     * @_inheritDoc
     */
    InspectorWindow.prototype.onGUI = function () {
        var _a = Application.instance, screen = _a.screen, stage = _a.stage;
        var size = screen.size;
        var rect = this._rect;
        var winWidth = screen.rotated ? (rect.h || size.h) : (rect.w || size.w);
        var winHeight = screen.rotated ? (rect.w || size.w) : (rect.h || size.h);
        ImGui.SetNextWindowPos(EditorWindowUtil.vector2ToImVec2((screen.rotated ? size.h : size.w) - winWidth, 0.0));
        ImGui.SetNextWindowSize(EditorWindowUtil.vector2ToImVec2(winWidth, winHeight));
        this._imguiCount = 0;
        // if (ImGui.Begin(this.title, (value: boolean = this._isOpened) => this._isOpened = value)) {
        if (ImGui.Begin(this.title)) {
            var tabBarFlags = ImGui.ImGuiTabBarFlags.None;
            if (ImGui.BeginTabBar("EntitiesTabBar", tabBarFlags)) {
                for (var _i = 0, _b = this._groups; _i < _b.length; _i++) {
                    var group = _b[_i];
                    for (var _c = 0, _d = group.entities; _c < _d.length; _c++) {
                        var entity = _d[_c];
                        var name_1 = "Entity###" + entity.uuid;
                        if (ImGui.BeginTabItem(name_1)) {
                            this._imEntity(entity);
                            ImGui.EndTabItem();
                        }
                    }
                }
            }
            ImGui.EndTabBar();
        }
        ImGui.End();
    };
    InspectorWindow = __decorate([
        component({ isAbstract: false })
    ], InspectorWindow);
    return InspectorWindow;
}(EditorWindow));
__reflect(InspectorWindow, "@egret/inspector/InspectorWindow");

/**
 *
 */
var HierarchyWindow = /** @class */ (function (_super) {
    __extends(HierarchyWindow, _super);
    function HierarchyWindow() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        /** */
        _this._imguiCount = 0;
        _this._tools = Application.instance.globalEntity.getComponent(Tools);
        _this._entitySelecteor = Application.instance.globalEntity.getComponent(EntitySelector);
        _this._groups = [];
        return _this;
    }
    /** */
    HierarchyWindow.prototype._imUUID = function (uuid) {
        ImGui.BeginTooltip();
        ImGui.PushTextWrapPos(ImGui.GetFontSize() * 20.0);
        ImGui.TextUnformatted("UUID: " + uuid.uuid);
        ImGui.PopTextWrapPos();
        ImGui.EndTooltip();
    };
    /** */
    HierarchyWindow.prototype._imContext = function (context) {
        var isControl = this._tools.isControl || this._tools.isMate;
        var spacing = ImGui.GetTreeNodeToLabelSpacing();
        if (context.entityClass === AssetEntity) {
            if (ImGui.CollapsingHeader(Reflect$1.getQualifiedClassName(context.entityClass))) {
                ImGui.Indent(spacing);
                for (var _i = 0, _a = context.entities; _i < _a.length; _i++) {
                    var entity = _a[_i];
                    var hideFiags = getHideFlags(entity);
                    if (hideFiags !== null && hideFiags.hide) {
                        continue;
                    }
                    var name_1 = entity.uri + "###H" + entity.uuid;
                    var selected = entity.getComponent(Selected) !== null;
                    if (ImGui.Selectable(name_1, selected)) {
                        this._entitySelecteor.select(entity, !isControl);
                    }
                    if (isControl && ImGui.IsItemHovered()) {
                        this._imUUID(entity);
                    }
                }
                ImGui.Unindent(spacing);
            }
        }
        else {
            if (ImGui.CollapsingHeader(Reflect$1.getQualifiedClassName(context.entityClass))) {
                ImGui.Indent(spacing);
                for (var _b = 0, _c = context.entities; _b < _c.length; _b++) {
                    var entity = _c[_b];
                    var hideFiags = getHideFlags(entity);
                    if (hideFiags !== null && hideFiags.hide) {
                        continue;
                    }
                    var name_2 = "Entity###H" + entity.uuid;
                    var selected = entity.getComponent(Selected) !== null;
                    if (ImGui.Selectable(name_2, selected)) {
                        this._entitySelecteor.select(entity, !isControl);
                    }
                    if (isControl && ImGui.IsItemHovered()) {
                        this._imUUID(entity);
                    }
                }
                ImGui.Unindent(spacing);
            }
        }
    };
    /** */
    HierarchyWindow.prototype._imScene = function (scene) {
        var nodeFlags = ImGui.ImGuiTreeNodeFlags.None;
        if (this._entitySelecteor.isInSelectedChain(scene.entity));
        //
        var opened = ImGui.CollapsingHeader(scene.name + " <Scene>##" + scene.uuid, nodeFlags);
        if (ImGui.IsItemClicked()) {
            this._entitySelecteor.select(scene.entity, true);
        }
        //
        if (opened) {
            var nodes = scene.root.children;
            for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
                var node = nodes_1[_i];
                var hideFiags = getHideFlags(node.entity);
                if (hideFiags !== null && hideFiags.hide) {
                    continue;
                }
                this._imTreeNode(node);
            }
        }
    };
    /** */
    HierarchyWindow.prototype._imTreeNode = function (treeNode) {
        var entitySelecteor = this._entitySelecteor;
        var isControl = this._tools.isControl || this._tools.isMate;
        var name = treeNode.name + "###H" + treeNode.uuid;
        var entity = treeNode.entity, children = treeNode.children;
        var nodeFlags = ImGui.ImGuiTreeNodeFlags.None;
        if (entitySelecteor.isEntitySelected(entity)) {
            nodeFlags |= ImGui.ImGuiTreeNodeFlags.Selected;
        }
        else if (entitySelecteor.isInSelectedChain(entity)) {
            nodeFlags |= ImGui.ImGuiTreeNodeFlags.DefaultOpen;
        }
        if (children.length > 0) {
            nodeFlags |= ImGui.ImGuiTreeNodeFlags.OpenOnArrow | ImGui.ImGuiTreeNodeFlags.OpenOnDoubleClick;
        }
        else {
            nodeFlags |= ImGui.ImGuiTreeNodeFlags.Leaf | ImGui.ImGuiTreeNodeFlags.NoTreePushOnOpen;
        }
        var opened = ImGui.TreeNodeEx(name, nodeFlags);
        if (ImGui.IsItemClicked()) {
            entitySelecteor.select(entity, !isControl);
        }
        if (isControl && ImGui.IsItemHovered()) {
            this._imUUID(entity);
        }
        if (opened && children.length > 0) {
            for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
                var child = children_1[_i];
                this._imTreeNode(child);
            }
            ImGui.TreePop();
        }
    };
    HierarchyWindow.prototype.initialize = function (defaultEnabled, entity, config) {
        var _this = this;
        if (config === void 0) { config = null; }
        _super.prototype.initialize.call(this, defaultEnabled, entity, config); // TODO
        var application = Application.instance;
        application.contexts.map(function (context) {
            _this._groups.push(context.getGroup(Matcher.create(context.entityClass, false, TreeNode)), context.getGroup(Matcher.create(context.entityClass, false, Selected)), context.getGroup(Matcher.create(context.entityClass, false, LastSelected)));
        });
    };
    /**
     * @_inheritDoc
     */
    HierarchyWindow.prototype.onGUI = function () {
        var _a = Application.instance, screen = _a.screen, stage = _a.stage;
        var size = screen.size;
        var rect = this._rect;
        this._imguiCount = 0;
        var winWidth = screen.rotated ? (rect.h || size.h) : (rect.w || size.w);
        var winHeight = screen.rotated ? (rect.w || size.w) : (rect.h || size.h);
        ImGui.SetNextWindowPos(EditorWindowUtil.vector2ToImVec2(0.0, 0.0));
        ImGui.SetNextWindowSize(EditorWindowUtil.vector2ToImVec2(winWidth, winHeight));
        if (ImGui.Begin(this.title)) {
            // Debug.
            var isDebug_1 = (Application.instance.executeMode & 4 /* Editor */) !== 0;
            if (ImGui.Checkbox("Debug###" + this._imguiCount++, function (value) {
                if (value === void 0) { value = isDebug_1; }
                return isDebug_1 = value;
            })) {
                if (isDebug_1) {
                    Application.instance.executeMode |= 4 /* Editor */;
                }
                else {
                    Application.instance.executeMode &= ~4 /* Editor */;
                }
            }
            // Entity Contexts.
            ImGui.Text("Entity Contexts");
            ImGui.Separator();
            for (var _i = 0, _b = Application.instance.contexts; _i < _b.length; _i++) {
                var context_1 = _b[_i];
                if (context_1.entityClass === GameEntity) {
                    continue;
                }
                this._imContext(context_1);
            }
            // Scenes.
            ImGui.Text("Scenes");
            ImGui.Separator();
            var sceneManager = Application.instance.sceneManager;
            this._imScene(sceneManager.globalScene);
            this._imScene(sceneManager.editorScene);
            for (var _c = 0, _d = sceneManager.scenes; _c < _d.length; _c++) {
                var scene = _d[_c];
                this._imScene(scene);
            }
        }
        ImGui.End();
    };
    HierarchyWindow = __decorate([
        component({ isAbstract: false })
    ], HierarchyWindow);
    return HierarchyWindow;
}(EditorWindow));
__reflect(HierarchyWindow, "@egret/inspector/HierarchyWindow");

/**
 * 状态窗口。
 */
var StatsWindow = /** @class */ (function (_super) {
    __extends(StatsWindow, _super);
    function StatsWindow() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        /** */
        _this._statsPanels = [];
        _this._statsPanelRecord = {};
        _this._statsPanel = null;
        return _this;
    }
    /**
     * @_inheritDoc
     */
    StatsWindow.prototype.onGUI = function (deltaTime) {
        var _this = this;
        var statsPanels = this._statsPanels;
        for (var _i = 0, statsPanels_1 = statsPanels; _i < statsPanels_1.length; _i++) {
            var statsPanel = statsPanels_1[_i];
            statsPanel.value = statsPanel.getValue !== null ? statsPanel.getValue(statsPanel, deltaTime) : 0.0;
            statsPanel.minimum = Math.min(statsPanel.value, statsPanel.minimum);
            statsPanel.maximum = Math.max(statsPanel.value, statsPanel.maximum);
            statsPanel.values[statsPanel.offset] = statsPanel.value;
            statsPanel.offset = (statsPanel.offset + 1) % 90;
        }
        //
        var _a = Application.instance, screen = _a.screen, stage = _a.stage;
        var winWidth = this._rect.w;
        var winHeight = this._rect.h || (screen.rotated ? screen.size.w : screen.size.h);
        var windowFlags = ImGui.WindowFlags;
        windowFlags = 0;
        windowFlags |= ImGui.ImGuiWindowFlags.NoResize;
        windowFlags |= ImGui.ImGuiWindowFlags.NoTitleBar;
        ImGui.SetNextWindowPos(EditorWindowUtil.vector2ToImVec2(this._rect));
        ImGui.SetNextWindowSize(EditorWindowUtil.vector2ToImVec2(winWidth, winHeight));
        //
        if (ImGui.Begin(this.title, function (value) {
            if (value === void 0) { value = _this._isOpened; }
            return _this._isOpened = value;
        }, windowFlags)) {
            // Change stats panel.
            if (statsPanels.length > 0) {
                if (this._statsPanel === null) {
                    this._statsPanel = statsPanels[0];
                }
                else if (ImGui.IsWindowHovered() && ImGui.IsMouseClicked(0)) {
                    var index = statsPanels.indexOf(this._statsPanel);
                    if (ImGui.GetIO().MousePos.x > ImGui.GetWindowPos().x + ImGui.GetWindowWidth() * 0.5) {
                        this._statsPanel = statsPanels[(index + 1) % statsPanels.length];
                    }
                    else {
                        this._statsPanel = statsPanels[(statsPanels.length + index - 1) % statsPanels.length];
                    }
                }
            }
            // Update stats panel.
            var statsPanel = this._statsPanel;
            if (statsPanel !== null) {
                ImGui.Text(statsPanel.title + ": " + Math.round(statsPanel.value) + " [" + Math.round(statsPanel.minimum) + "-" + Math.round(statsPanel.maximum) + "]");
                ImGui.PushStyleColor(ImGui.ImGuiCol.PlotHistogram, EditorWindowUtil.colorToImColor(statsPanel.color));
                ImGui.SetNextItemWidth(130.0);
                ImGui.PlotHistogram("", statsPanel.values, statsPanel.values.length, statsPanel.offset, null, statsPanel.minimum, statsPanel.maximum, EditorWindowUtil.vector2ToImVec2(0.0, 45.0));
            }
        }
        ImGui.End();
    };
    /**
     *
     * @param name
     * @param param1
     */
    StatsWindow.prototype.addPanel = function (name, _a) {
        var _b = _a === void 0 ? {} : _a, _c = _b.title, title = _c === void 0 ? "" : _c, _d = _b.color, color = _d === void 0 ? null : _d, _e = _b.getValue, getValue = _e === void 0 ? null : _e;
        var statsPanelRecord = this._statsPanelRecord;
        if (name in statsPanelRecord) {
            {
                console.warn("The panel has been added.", name);
            }
            return false;
        }
        // Create panel.
        var statsPanel = statsPanelRecord[name] = {
            title: title || name,
            color: Color.create(),
            offset: 0,
            minimum: Infinity,
            maximum: -Infinity,
            value: 0.0,
            values: new Array(90).fill(0.0),
            getValue: getValue,
        };
        if (color !== null) {
            statsPanel.color.copy(color);
        }
        this._statsPanels.push(statsPanel);
        return true;
    };
    /**
     *
     * @param name
     */
    StatsWindow.prototype.removePanel = function (name) {
        var statsPanelRecord = this._statsPanelRecord;
        if (name in statsPanelRecord) {
            var statsPanel = statsPanelRecord[name];
            if (this._statsPanel === statsPanel) {
                this._statsPanel = null;
            }
            delete statsPanelRecord[name];
            this._statsPanels.splice(this._statsPanels.indexOf(statsPanel), 1);
            return true;
        }
        //
        {
            console.warn("The panel has been removed.", name);
        }
        return false;
    };
    StatsWindow = __decorate([
        component({ isAbstract: false })
    ], StatsWindow);
    return StatsWindow;
}(EditorWindow));
__reflect(StatsWindow, "@egret/inspector/StatsWindow");

/**
 * 全局 Inspector 信息组件。
 * @public
 */
var InspectorComponent = /** @class */ (function (_super) {
    __extends(InspectorComponent, _super);
    function InspectorComponent() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    InspectorComponent = __decorate([
        hideFlag(16 /* HideInMenu */ | 8 /* Hide */ | 4 /* DontSave */),
        component({ isRemovable: false, isAbstract: false })
    ], InspectorComponent);
    return InspectorComponent;
}(Component));
__reflect(InspectorComponent, "@egret/inspector/InspectorComponent");

/**
 * @public
 */
var InspectorSystem = /** @class */ (function (_super) {
    __extends(InspectorSystem, _super);
    function InspectorSystem() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        /** */
        _this._inspectorWindow = null;
        _this._hierarchyWindow = null;
        _this._statsWindow = null;
        return _this;
    }
    /** */
    InspectorSystem.prototype._closeAllWindows = function () {
        if (this._inspectorWindow !== null) {
            this._inspectorWindow.close();
        }
        if (this._hierarchyWindow !== null) {
            this._hierarchyWindow.close();
        }
        if (this._statsWindow !== null) {
            this._statsWindow.close();
        }
        this._inspectorWindow = null;
        this._hierarchyWindow = null;
        this._statsWindow = null;
    };
    /** */
    InspectorSystem.prototype._toggleWindows = function () {
        if (this._inspectorWindow !== null) {
            this._inspectorWindow.isOpened ? this._inspectorWindow.hide() : this._inspectorWindow.show();
        }
        if (this._hierarchyWindow !== null) {
            this._hierarchyWindow.isOpened ? this._hierarchyWindow.hide() : this._hierarchyWindow.show();
        }
        if (this._statsWindow !== null) {
            this._statsWindow.isOpened ? this._statsWindow.hide() : this._statsWindow.show();
        }
    };
    /**
     * @_inheritDoc
     */
    InspectorSystem.prototype.onStart = function () {
        Application.instance.globalEntity.addComponent(InspectorComponent);
    };
    /**
     * @_inheritDoc
     */
    InspectorSystem.prototype.onEnable = function () {
        this._inspectorWindow = EditorWindowUtil.createWindow(InspectorWindow, { title: "Inspector", rect: Rectangle.create(0.0, 0.0, 300.0, 0.0) });
        this._hierarchyWindow = EditorWindowUtil.createWindow(HierarchyWindow, { title: "Hierarchy", rect: Rectangle.create(0.0, 0.0, 240.0, 0.0) });
        this._statsWindow = EditorWindowUtil.createWindow(StatsWindow, { title: "Stats", rect: Rectangle.create(240, 0, 140, 80) });
        this._statsWindow.addPanel("FPS", {
            getValue: function (statsPanel) {
                if (!statsPanel.userData) {
                    statsPanel.userData = {
                        frames: 0,
                        deltaTime: 0.0,
                    };
                }
                //
                var userData = statsPanel.userData;
                var clock = Application.instance.clock;
                userData.frames += clock.deltaFrameCount;
                userData.deltaTime += clock.unscaledFrameDeltaTime;
                if (userData.deltaTime > 1.0) {
                    var value = userData.frames / userData.deltaTime;
                    userData.frames = 0;
                    userData.deltaTime = 0.0;
                    return value;
                }
                return statsPanel.value;
            }
        });
        this._statsWindow.addPanel("TPS", {
            getValue: function (statsPanel) {
                if (!statsPanel.userData) {
                    statsPanel.userData = {
                        frames: 0,
                        deltaTime: 0.0,
                    };
                }
                //
                var userData = statsPanel.userData;
                var clock = Application.instance.clock;
                userData.deltaTime += clock.unscaledFrameDeltaTime;
                if (userData.deltaTime > 1.0) {
                    var value = (clock.tickCount - userData.frames) / userData.deltaTime;
                    userData.frames = clock.tickCount;
                    userData.deltaTime = 0.0;
                    return value;
                }
                return statsPanel.value;
            }
        });
        // this._statsWindow.addPanel("Whole", {
        //     getValue: () => {
        //         return Application.instance.clock.wholeCost;
        //     }
        // });
        this._statsWindow.addPanel("Total", {
            getValue: function () {
                return Application.instance.clock.totalCost;
            }
        });
        this._statsWindow.addPanel("Tick", {
            getValue: function () {
                return Application.instance.clock.tickCost;
            }
        });
        this._statsWindow.addPanel("Frame", {
            getValue: function () {
                return Application.instance.clock.frameCost;
            }
        });
        this._statsWindow.addPanel("Draw", {
            getValue: function () {
                var drawcallcollector = Application.instance.globalEntity.getComponent(DrawCallCollector);
                return drawcallcollector.drawCallCount;
            }
        });
        this._inspectorWindow.show();
        this._hierarchyWindow.show();
        this._statsWindow.show();
    };
    /**
     * @_inheritDoc
     */
    InspectorSystem.prototype.onDisable = function () {
        this._closeAllWindows();
    };
    /**
     * @_inheritDoc
     */
    InspectorSystem.prototype.onTick = function () {
        if (this.tools.inputManager.getInput("KeyH" /* KeyH */).isUp) {
            this._toggleWindows();
        }
    };
    InspectorSystem = __decorate([
        system({ anyOfExecuteMode: 1 /* Running */ })
    ], InspectorSystem);
    return InspectorSystem;
}(BaseEditorSystem));
__reflect(InspectorSystem, "@egret/inspector/InspectorSystem");

/**
 * Module startup.
 */
function startup() {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            if (!EngineUtil.isWebView) {
                return [2 /*return*/];
            } // TODO
            SystemManager.preRegisterSystem(InspectorSystem, 6000 /* LateUpdate */);
            return [2 /*return*/];
        });
    });
}

export { startup };
